package cn.amebius.simpledocker.websocket;

import com.Ostermiller.util.CircularByteBuffer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 阿伟
 * @date 2023/9/26 14:26
 */
@Slf4j
public class TextAbstractWebsocket extends TextWebSocketHandler {

    private static final Map<String, InputStream> ins = new ConcurrentHashMap<>();

    private static final Map<String, OutputStream> outs = new ConcurrentHashMap<>();

    /**
     * WebSocket的名称
     */
    private String name;

    public TextAbstractWebsocket() {
        super();
    }

    public void initSocket(String name) {
        this.name = name;
        log.info("【{}】开启监听",this.name);
    }


    /**
     * 功能描述：连接建立后执行操作
     *
     * @author HeJiaWei
     * @date 2/6/24
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session){
        String sessionId = session.getId();
        final CircularByteBuffer cbb = new CircularByteBuffer();
        final InputStream in = cbb.getInputStream();
        final OutputStream out = cbb.getOutputStream();
        ins.put(sessionId, in);
        outs.put(sessionId, out);
        log.info("【{}】[{}]开启socket",this.name,sessionId);
    }

    /**
     * 向执行的DockerCmd中发送命令
     * @param session socket的会话seesion
     * @param msg   发送信息的msg
     * @throws IOException io错误
     */
    public void sendCmd(WebSocketSession session,byte[] msg) throws IOException {
        isConnect(session);
        String sessionId = session.getId();
        OutputStream os = outs.get(sessionId);
        os.write(msg);
        log.info("【{}】[{}]接收消息:{}",this.name,sessionId,new String(msg));
    }

    /**
     * 向websocket的前端发送信息
     * @param session socket的会话seesion
     * @param msg 发送信息的msg
     * @throws IOException
     */
    public void sendMessage(WebSocketSession session,byte[] msg) throws IOException {
        isConnect(session);
        String sessionId = session.getId();
        session.sendMessage(new BinaryMessage(msg));
        //log.info("【{}】[{}]发送消息:{}",this.name,sessionId,new String(msg));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status){
        String sessionId = session.getId();
        try {
            InputStream is = ins.get(sessionId);
            OutputStream os = outs.get(sessionId);
            is.close();
            os.close();
            ins.remove(sessionId);
            outs.remove(sessionId);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            log.info("【{}】[{}]关闭socket",this.name,sessionId);
        }
    }

    public InputStream getInput(String sessionId) {
        return ins.get(sessionId);
    }

    public void isConnect(WebSocketSession session) {
        String sessionId = session.getId();
        if (session == null || !session.isOpen()) {
            try {
                session.close();
                InputStream is = ins.get(sessionId);
                OutputStream os = outs.get(sessionId);
                is.close();
                os.close();
                ins.remove(sessionId);
                outs.remove(sessionId);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                log.error("【{}】[{}]异常退出",this.name,sessionId);
                //throw Expection
            }
        }
    }

}
